#ifndef VECTOR_IMPL_H_
#define VECTOR_IMPL_H_

#define IMPL_QUAL_VEC(TYPE, QUAL) \
QUAL size_t ctl_vec_##TYPE##_size(ctl_vec_##TYPE* vec) { \
  return vec->size; \
} \
QUAL size_t ctl_vec_##TYPE##_begin_idx(ctl_vec_##TYPE* vec) { \
  return vec->begin_idx; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_ctor_with_size(ctl_vec_##TYPE *vec, size_t size) { \
  ctl_res_void res_void = {0}; \
  res_void.ec = EOK; \
  vec->begin_idx = 0; \
  vec->size = size; \
  vec->capacity = size; \
  vec->data = (TYPE *)malloc(vec->capacity * sizeof(TYPE)); \
  /* 初始化就要初始化所有分配的内存 */  \
  for (size_t idx = 0; idx < vec->capacity; idx++) { \
    CHECK_EXEC_RES_RET_RES(TYPE##_ctor(vec->data + idx), res_void, res_void); \
  } \
  return res_void; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_ctor(ctl_vec_##TYPE *vec) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  CHECK_EXEC_RES_RET_RES(ctl_vec_##TYPE##_ctor_with_size(vec, CTL_VEC_MINIMAL_SIZE), res, res) ; \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_dtor(ctl_vec_##TYPE *vec) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  /* 销毁就要销毁所有分配的内存 */ \
  for (size_t idx = 0; idx < vec->capacity; idx++) { \
    CHECK_EXEC_RES_RET_RES(TYPE##_dtor(vec->data + idx), res, res); \
  } \
  free(vec->data); \
  vec->data = NULL; \
  return res; \
} \
QUAL ctl_res_ctl_vec_##TYPE##_p ctl_vec_##TYPE##_new(size_t size) { \
  ctl_res_ctl_vec_##TYPE##_p res = {0}; \
  res.ec = EOK; \
  ctl_res_void res_void = {0}; \
  res_void.ec = EOK; \
  ctl_vec_##TYPE *vec = (ctl_vec_##TYPE *)malloc(sizeof(ctl_vec_##TYPE)); \
  CHECK_COND_RET_RES(NULL != vec, EOOM, res); \
  res.value = vec; \
  CHECK_EXEC_RES_POSTPROC_RET_RES(ctl_vec_##TYPE##_ctor_with_size(res.value, size), res_void, res, free(vec)); \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_free(ctl_vec_##TYPE *vec) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  CHECK_EXEC_RES_RET_RES(ctl_vec_##TYPE##_dtor(vec), res, res); \
  free(vec); \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_clear(ctl_vec_##TYPE* vec) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  vec->begin_idx = 0U; \
  vec->size = 0U; \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_reserve(ctl_vec_##TYPE *vec, size_t new_capacity) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  CHECK_COND_RET_RES(new_capacity != 0, EINVALID_PARAM, res); \
  if (new_capacity <= vec->capacity) { \
    return res; \
  } \
  vec->capacity = new_capacity; \
  /* 先申请内存，然后初始化 */ \
  TYPE *new_data = (TYPE *)malloc(vec->capacity * sizeof(TYPE)); \
  CHECK_COND_RET_RES(new_data != NULL, EOOM, res); \
  for (size_t idx = 0; idx < vec->capacity; idx++) { \
    CHECK_EXEC_RES_RET_RES(TYPE##_ctor(new_data + idx), res, res); \
  } \
  /* 把旧的内容拷贝过来 */ \
  for (size_t idx = 0; idx < vec->size; idx++) { \
    CHECK_EXEC_RES_RET_RES(TYPE##_copy(new_data + idx, vec->data + idx), res, res); \
  } \
  /* 销毁掉旧的内容 */ \
  for (size_t idx = 0; idx < vec->capacity; idx++) { \
    CHECK_EXEC_RES_RET_RES(TYPE##_dtor(vec->data + idx), res, res); \
  } \
  free(vec->data); \
  vec->data = new_data; \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_resize(ctl_vec_##TYPE *vec, size_t new_size) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  if (vec->begin_idx + new_size > vec->capacity) { \
    CHECK_EXEC_RES_RET_RES(ctl_vec_##TYPE##_reserve(vec, vec->begin_idx + new_size), res, res); \
  } \
  vec->size = new_size; \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_copy(ctl_vec_##TYPE *dst, const ctl_vec_##TYPE *src) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  dst->size = src->size; \
  /* 如果src的capacity已经比dst的capacity更大，那dst就要释放掉之前的内存，然后重新申请内存 */ \
  if (dst->capacity < src->size) { \
    if (dst->data) { \
      /* 释放掉dst的资源 */ \
      for (size_t idx = 0; idx < dst->capacity; idx++) { \
        CHECK_EXEC_RES_RET_RES(TYPE##_dtor(dst->data + idx), res, res); \
      } \
      free(dst->data); \
    } \
    /* 必须要最后赋值，因为先释放后申请 */ \
    dst->capacity = src->size; \
    /* 为dst申请资源然后初始化 */ \
    dst->data = (TYPE *)malloc(dst->capacity * sizeof(TYPE)); \
    CHECK_COND_RET_RES(dst->data != NULL, EOOM, res); \
    for (size_t idx = 0; idx < src->size; idx++) { \
      CHECK_EXEC_RES_RET_RES(TYPE##_ctor(dst->data + idx), res, res); \
    } \
  } \
  dst->begin_idx = 0; \
  dst->size = src->size; \
  /* 然后拷贝 */ \
  for (size_t idx = 0; idx < src->size; idx++) { \
    CHECK_EXEC_RES_RET_RES(TYPE##_copy(dst->data + idx, src->data + (idx + src->begin_idx)), res, res); \
  } \
  return res; \
} \
QUAL ctl_res_##TYPE ctl_vec_##TYPE##_get_at(ctl_vec_##TYPE *vec, size_t index) { \
  ctl_res_##TYPE res = {0}; \
  res.ec = EOK; \
  CHECK_COND_RET_RES (index < vec->size, EINDEX_OVERFLOW, res); \
  ctl_res_void res_void = {0}; \
  res_void.ec =  EOK; \
  CHECK_EXEC_RES_RET_RES(TYPE##_copy(&(res.value), vec->data + (vec->begin_idx + index)), res_void, res); \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_set_at(ctl_vec_##TYPE *vec, size_t index, const TYPE value) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  CHECK_COND_RET_RES (index < vec->size, EINDEX_OVERFLOW, res); \
  CHECK_EXEC_RES_RET_RES(TYPE##_copy(vec->data + (vec->begin_idx + index), &value), res, res); \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_grow(ctl_vec_##TYPE *vec) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  size_t new_capacity = vec->capacity * CTL_VEC_GROW_FACTOR; \
  CHECK_EXEC_RES_RET_RES(ctl_vec_##TYPE##_reserve(vec, new_capacity), res, res); \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_push_back(ctl_vec_##TYPE *vec, const TYPE data) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  if (vec->capacity == (vec->begin_idx + vec->size)) { \
    ctl_vec_##TYPE##_grow(vec); \
  } \
  CHECK_EXEC_RES_RET_RES(TYPE##_copy(vec->  data + (vec->begin_idx + vec->size), &data), res, res); \
  vec->size++; \
  return res; \
} \
QUAL ctl_res_##TYPE ctl_vec_##TYPE##_pop_back(ctl_vec_##TYPE *vec) { \
  ctl_res_##TYPE res = {0}; \
  res.ec = EOK; \
  ctl_res_void res_void = {0}; \
  res_void.ec = EOK; \
  CHECK_COND_RET_RES (vec->size != 0, EEMPTY, res); \
  CHECK_EXEC_RES_RET_RES(TYPE##_copy(&(res.value), vec-> data + (vec->begin_idx + vec->size - 1U)), res_void, res); \
  vec->size--; \
  return res; \
} \
/* 往后移动要从后往前移动，避免内存踩踏 */ \
QUAL ctl_res_void _ctl_vec_##TYPE##_move_backward(ctl_vec_##TYPE *vec, size_t from_idx, size_t to_idx, \
                              size_t count) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  for (size_t idx = count; idx > 0; idx--) { \
    CHECK_EXEC_RES_RET_RES(TYPE##_copy(vec->data + (to_idx + idx - 1U), vec->data + (from_idx + idx - 1U)), res, res); \
  } \
  return res; \
} \
/* 往后移动要从前往后移动，避免内存踩踏 */ \
QUAL ctl_res_void _ctl_vec_##TYPE##_move_forward(ctl_vec_##TYPE *vec, size_t from_idx, size_t to_idx, \
                             size_t count) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  for (size_t idx = 0; idx < count; idx++) { \
    CHECK_EXEC_RES_RET_RES(TYPE##_copy(vec->data + to_idx + idx, vec->data + from_idx + idx), res, res); \
  } \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_trim(ctl_vec_##TYPE *vec) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  CHECK_EXEC_RES_RET_RES(_ctl_vec_##TYPE##_move_forward(vec, vec->begin_idx, 0, vec->size), res, res); \
  vec->begin_idx = 0; \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_insert_range(ctl_vec_##TYPE *vec, size_t insert_start_idx, \
                               size_t insert_count, \
                               const TYPE *data_arr) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  if (vec->size + vec->begin_idx + insert_count > vec->capacity) { \
    size_t new_capacity = vec->capacity; \
    while (vec->size + vec->begin_idx + insert_count > new_capacity) { \
      new_capacity = new_capacity * CTL_VEC_GROW_FACTOR; \
    } \
    TYPE *new_data = (TYPE *)malloc(new_capacity * sizeof(TYPE)); \
    CHECK_COND_RET_RES(new_data != NULL, EOOM, res); \
    for (size_t idx = 0; idx < new_capacity; idx++) { \
      CHECK_EXEC_RES_RET_RES(TYPE##_ctor(new_data + idx), res, res); \
    } \
    for (size_t idx = vec->begin_idx; idx < vec->begin_idx + insert_start_idx; idx++) { \
      CHECK_EXEC_RES_RET_RES(TYPE##_copy(new_data + idx, vec->data + idx), res, res); \
    } \
    for (size_t idx = 0; idx < insert_count; idx++) { \
      CHECK_EXEC_RES_RET_RES(TYPE##_copy(new_data + (vec->begin_idx + insert_start_idx + idx), data_arr + idx), res, res); \
    } \
    for (size_t idx = vec->begin_idx + insert_start_idx; idx < vec->begin_idx + vec->size; idx++) { \
      CHECK_EXEC_RES_RET_RES(TYPE##_copy(new_data + (idx + insert_count), vec->data + idx), res, res); \
    } \
    for (size_t idx = 0; idx < vec->size; idx++) { \
      CHECK_EXEC_RES_RET_RES(TYPE##_dtor(vec->data + vec->begin_idx + idx), res, res); \
    } \
    free(vec->data); \
    vec->capacity = new_capacity; \
    vec->data = new_data; \
  } else { \
    CHECK_EXEC_RES_RET_RES(_ctl_vec_##TYPE##_move_backward(vec, vec->begin_idx + insert_start_idx, \
                        vec->begin_idx + insert_start_idx + insert_count, \
                        vec->size - insert_start_idx), res, res); \
    for (size_t idx = 0; idx < insert_count; idx++) { \
      CHECK_EXEC_RES_RET_RES(TYPE##_copy(vec->data + (vec->begin_idx + insert_start_idx + idx), data_arr + idx), res, res); \
    } \
  } \
  vec->size += insert_count; \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_insert_at(ctl_vec_##TYPE* vec, size_t insert_idx, const TYPE data) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  CHECK_EXEC_RES_RET_RES(ctl_vec_##TYPE##_insert_range(vec, insert_idx, 1, &data), res, res); \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_remove_range(ctl_vec_##TYPE *vec, size_t remove_idx, size_t remove_count) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  CHECK_COND_RET_RES(remove_idx + remove_count <= vec->size, EINDEX_OVERFLOW, res); \
  CHECK_EXEC_RES_RET_RES(_ctl_vec_##TYPE##_move_forward(vec, vec->begin_idx + remove_idx + remove_count, vec->begin_idx + remove_idx, \
                     vec->size - remove_idx - remove_count), res, res); \
  vec->size -= remove_count; \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_remove_at(ctl_vec_##TYPE *vec, size_t remove_idx) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  CHECK_EXEC_RES_RET_RES(ctl_vec_##TYPE##_remove_range(vec, remove_idx, 1), res, res); \
  return res; \
} \
QUAL ctl_res_void ctl_vec_##TYPE##_push_front(ctl_vec_##TYPE *vec, const TYPE data) { \
  ctl_res_void res = {0}; \
  res.ec = EOK; \
  if (vec->begin_idx > 0) { \
    CHECK_EXEC_RES_RET_RES(TYPE##_copy(vec->data + vec->begin_idx - 1, &data), res, res); \
    vec->begin_idx--; \
    vec->size++; \
  } else { \
    CHECK_EXEC_RES_RET_RES(ctl_vec_##TYPE##_insert_at(vec, 0, data), res, res); \
  } \
  return res; \
} \
QUAL ctl_res_##TYPE ctl_vec_##TYPE##_pop_front(ctl_vec_##TYPE *vec) { \
 ctl_res_##TYPE res = {0}; \
 res.ec = EOK; \
 ctl_res_void res_void = {0}; \
 res_void.ec = EOK; \
 CHECK_COND_RET_RES(vec->size != 0, EEMPTY, res); \
 CHECK_EXEC_RES_RET_RES(TYPE##_copy(&(res.value), vec->data + vec->begin_idx), res_void, res); \
 vec->begin_idx++;  \
 vec->size--; \
 if (vec->begin_idx == (size_t)((double)vec->capacity * CTL_VEC_TRIM_RATIO)) { \
  CHECK_EXEC_RES_RET_RES(ctl_vec_##TYPE##_trim(vec), res_void, res); \
 } \
 return res; \
}

#define IMPL_VEC(TYPE) IMPL_QUAL_VEC(TYPE, )
#define IMPL_STATIC_VEC(TYPE) IMPL_QUAL_VEC(TYPE, static)
#define IMPL_INLINE_STATIC_VEC(TYPE) IMPL_QUAL_VEC(TYPE, inline static)
#endif